/**
 * Description:实现客户端测量距离和面积的功能
 * version: 1.0.0
 */
define([
    "dojo/_base/declare",
    "esri/Graphic",
    "esri/views/2d/draw/Draw",
    "esri/geometry/Polygon",
    "esri/geometry/geometryEngine",
    "esri/geometry/Polyline",
    "esri/geometry/Point",
    "esri/geometry/SpatialReference",
    "esri/layers/GraphicsLayer",
    "esri/symbols/SimpleMarkerSymbol",
    "dojo/dom-construct",
    "dojo/domReady!"
], function (declare,Graphic,Draw,Polygon,geometryEngine,Polyline,Point,SpatialReference,GraphicsLayer,SimpleMarkerSymbol,domConstruct) {
    return declare(null, {
       _tpl :dojo.string.substitute,
    resultTemplate: '<div class="result-div" data-randomid="${randomId}" data-mapx="${mapx}" data-mapy="${mapy}" style="position:absolute;left:${screenx}px;top:${screeny}px;border: 1px solid #FF0103;padding: 4px;background:#fff;font-size:14px;"><span style="font-weight:700;color:#ff6319">${resultType}${result}</span> ${unit}</div>',
    processTemplate: '<div class="result-div" data-randomid="${randomId}" data-mapx="${mapx}" data-mapy="${mapy}" style="position:absolute;left:${screenx}px;top:${screeny}px;border: 1px solid rgb(136,136,136);background:#fff;font-size:12px;"><span style="font-weight:700;color:#ff6319">${result}</span> ${unit}</div>',
    clearTemplate: '<div id="clear-${randomId}" data-left-offset="${leftOffset}" data-mapx="${mapx}" data-mapy="${mapy}" data-randomid="${randomId}" class="clear-div" title="清除此次测量" style="cursor:pointer;font-family: cursive;border: 1px solid red;height: 12px;display: inline-block;width: 12px;line-height: 8px;font-weight: bolder;color: red;text-align: center;position:absolute;left:${left}px;top:${top}px">x</div>',

    /**
         * 成员属性
         * @type {string}
         */
        _mapView:null,
        geometryEngine:null,
        polygon:null,
        divMeasureAreaId:"",
        divMeasureLineId:"",
        _draw:null,
        toolname:null,
        _options:null,
        tools:{
            AREA: 'area',
            LENGTH: 'length'
        },


    urls:{

        },
        curSeqId:null,
        /**
         * 获取素有通用的元素
         * (建议通过function的方式返回，防止因为缓存的原因导致元素事件无法激活)
         * @returns
         */
        elements:function(){//每次加载后均需要重新选择
            return{
            };
        },
        /**
         * 构造函数（初始化函数）
         */
        constructor: function (view,toolname,options) {
            this._mapView=view;
            this.toolname=toolname;
            options || (options = {});
            options.coordinates || (options.coordinates = 'projected'); // 投影坐标系和地理坐标系计算方式不一样 geodesic
            this._options = options;
            this.init();

        },


        /**
         * 初始化函数
         */
        init:function () {
            var that=this;
            this.initUIEvent();
            this.initOpt();
            this.activate(this.toolname,this.params);
            this._mapView.when(function(instance){
                that._mapView.on('drag',function (e) {
                    that._calResultDiv();
                });
                that._mapView.on('mouse-wheel',function (e) {
                    that._calResultDiv();
                });
            })
        },
        initOpt:function () {
            var that=this;
            that._draw = new Draw({view: that._mapView });
            that._tempGraphicLayer = new GraphicsLayer(); // 绘制时的图层
            that._mapView.map.add(this._tempGraphicLayer);
            this._drawNodeGraphicLayer = new GraphicsLayer(); // 绘制时拐点图层
            this._mapView.map.add(this._drawNodeGraphicLayer);
        },
        initUIEvent:function () {
            var that=this;
        },

        /**
         * 激活事件
         * @param name
         * @param params
         */
        activate: function (name, params) {
            try{
                $('#mapdiv').css('cursor', 'crosshair');
                var that=this;
                that.toolname = name;
                params || (params = {});
                this._unit = params.unit;
                this._parseResult = params.parseResult; // 结果转换方法
                this._customUnit = params.customUnit; // 自定义单位名称
                this._decimal = params.decimal; // 保留小数位数
                switch (name) {
                    case that.tools.AREA:
                        this.enableCreatePolygon(that._draw); break;
                    case that.tools.LENGTH:
                        this.enableCreatePolyline(that._draw); break;
                };
                this._currentRandomId = (new Date()).valueOf();
            }catch (e) {
                
            }

        },

        //测量面积
        enableCreatePolygon: function (draw) {
            var that=this;
            var action = draw.create("polygon", {mode: "click"});
            that._mapView.focus();
            action.on("vertex-add", function (evt) {
                that._tempGraphicLayer.removeAll();
                var vertices = evt.vertices;
                var polygon = that.createPolygon(vertices);;
                var graphic = that.createGraphic(polygon);
                graphic.attributes = dojo.mixin(graphic.attributes, {
                    randomId: that._currentRandomId
                });
                that._tempGraphicLayer.add(graphic);
                var result = that._measure(polygon);
                if (result) {
                    that.toolname === that.tools.AREA && that._clearCurrentResultDivs(); // 如果是面积测量则清除上一次的测量结果
                    var point=polygon.centroid;
                    that._createResultDiv(result, point); // 添加测量结果信息div
                }
                if(vertices.length>0){
                    var point=new Point(vertices[vertices.length-1][0],vertices[vertices.length-1][1],that._mapView.spatialReference)
                    that._createDrawNode(point); // 绘制拐点
                }
            });
            action.on("cursor-update", function (evt) {
                that._tempGraphicLayer.removeAll();
                var vertices = evt.vertices;
                var polygon = that.createPolygon(vertices);;
                var graphic = that.createGraphic(polygon);
                graphic.attributes = dojo.mixin(graphic.attributes, {
                    randomId: that._currentRandomId
                });
                that._tempGraphicLayer.add(graphic);
            });

            action.on("draw-complete", function (evt) {
                that._tempGraphicLayer.removeAll();
                var vertices = evt.vertices;
                var polygon = that.createPolygon(vertices);
                var graphic = that.createGraphic(polygon);

                var result = that._measure(polygon);
                var mapPoint=polygon.centroid;
                if (result) {
                    that.toolname === that.tools.AREA && that._clearCurrentResultDivs();
                    that._createResultDiv(result,mapPoint);
                }
                graphic.attributes = dojo.mixin(graphic.attributes, {
                    randomId: that._currentRandomId
                });
                graphic.mapPoint=mapPoint;
                that._tempGraphicLayer.add(graphic);
                // that._createDrawNode(mapPoint);
                that._createClearDiv(graphic); // 创建清除测量按钮

                $('#mapdiv').css('cursor', 'default');
            });
        },
        lastLength:0,
        //测量长度
        enableCreatePolyline:function (draw) {
            var that=this;
            var action = draw.create("polyline", {mode: "click"});
            action.on("vertex-add", function (evt) {
                that._tempGraphicLayer.removeAll();
                var vertices = evt.vertices;
                var polyline = that.createPolyline(vertices);
                var graphic = that.createPolylineGraphic(polyline);
                graphic.attributes = dojo.mixin(graphic.attributes, {
                    randomId: that._currentRandomId
                });
                that._tempGraphicLayer.add(graphic);
                var result = that._measure(polyline);
                var twoLineLength=result- that.lastLength;
                that.lastLength=result;
                if(result&&vertices.length>0){
                    var point=new Point(vertices[vertices.length-1][0],vertices[vertices.length-1][1],that._mapView.spatialReference);
                    that._createProcessResultDiv(twoLineLength, point); // 添加测量结果信息div
                    graphic.attributes = dojo.mixin(graphic.attributes, {
                        randomId: that._currentRandomId
                    });
                    graphic.mapPoint=point;
                    that._createDrawNode(point); // 绘制拐点
                    // that._createClearDiv(graphic); // 创建清除测量按钮
                }
            });
            action.on("cursor-update", function (evt) {
                that._tempGraphicLayer.removeAll();
                var vertices = evt.vertices;
                var polyline = that.createPolyline(vertices);
                var graphic = that.createPolylineGraphic(polyline);
                graphic.attributes = dojo.mixin(graphic.attributes, {
                    randomId: that._currentRandomId
                });
                that._tempGraphicLayer.add(graphic);
            });
            action.on("draw-complete", function (evt) {
                var vertices = evt.vertices;
                var polyline = that.createPolyline(vertices);
                var graphic = that.createPolylineGraphic(polyline);
                graphic.attributes = dojo.mixin(graphic.attributes, {
                    randomId: that._currentRandomId
                });
                var result = that._measure(polyline);
                if(result&&vertices.length>0) {
                    var point = new Point(vertices[vertices.length - 1][0], vertices[vertices.length - 1][1], that._mapView.spatialReference);
                    that._createResultDiv(result, point); // 添加测量结果信息div
                    graphic.attributes = dojo.mixin(graphic.attributes, {
                        randomId: that._currentRandomId
                    });
                    graphic.mapPoint = point;
                    that._createClearDiv(graphic); // 创建清除测量按钮
                }
                $('#mapdiv').css('cursor', 'default');
            });
        },

        unitCh: {
            'square-meters': '平方米',
            'kilo-meters': '平方公里',
            'meters': '米',
            'kilometer': '公里',
        },
        _createClearDiv: function (g) {
            var that=this;
            var screen = that._mapView.toScreen(g.mapPoint);
            var lastTwoPoints = []; // 测量完成后geometry得最后两个点
            switch (g.geometry.type) {
                case 'polygon':
                    var lastRing = g.geometry.rings[g.geometry.rings.length-1];
                    if (lastRing && lastRing.length > 2) {
                        lastTwoPoints = [lastRing[lastRing.length - 1], lastRing[lastRing.length - 2]];
                    }
                    break;
                case 'polyline':
                    var lastPath = g.geometry.paths[g.geometry.paths.length-1];
                    if (lastPath && lastPath.length >= 2) {
                        lastTwoPoints = [lastPath[lastPath.length - 1], lastPath[lastPath.length - 2]];
                    }
                    break;
            }
            var pixel = 0;
            if (lastTwoPoints.length === 2) { // 根据最后两个点的连线计算清除按钮放置点的左边还是右边
                if (lastTwoPoints[0][0] >= lastTwoPoints[1][0]) {
                    pixel = 10;
                } else {
                    pixel = -20;
                }
            }
            var html = that._tpl(that.clearTemplate, {
                left: screen.x + pixel,
                top: screen.y - 7,
                randomId: this._currentRandomId,
                mapx: g.mapPoint.x,
                mapy: g.mapPoint.y,
                leftOffset: pixel
            });
            dojo.query(this._mapView.container).query('.esri-view-root').addContent(html);
            // 清除测量结果的点击事件，
            var handler = dojo.query('#clear-' + this._currentRandomId).on('click', function (event) {
                that._clearMeasureResult(event);
                handler[0].remove(); // 清除后移除该事件
            });
        },
        _clearMeasureResult: function (event) {
            var that = this;
            var randomId = dojo.query(event.currentTarget).attr('data-randomid')[0];
            dojo.query('[data-randomid="' + randomId + '"]').forEach(function (node) { // 移除添加的结果呈现div
                domConstruct.destroy(node);
            });
            this._tempGraphicLayer.removeMany(dojo.filter(this._tempGraphicLayer.graphics.items, function (g) {
                return g.attributes['randomId'] == randomId;
            }));
            this._drawNodeGraphicLayer.removeMany(dojo.filter(this._drawNodeGraphicLayer.graphics.items, function (g) {
                return g.attributes['randomId'] == randomId;
            }));
        },
        _createDrawNode: function (mapPoint) { // 创建节点
            var g = new Graphic({
                geometry: mapPoint,
                symbol: new SimpleMarkerSymbol({
                    style: "circle",
                    color: "white",
                    size: "6px",
                    outline: {
                        color: [255, 0, 0],
                        width: 2
                    }
                }),
                attributes: {
                    randomId: this._currentRandomId
                }
            });
            this._drawNodeGraphicLayer.add(g);
        },
        _clearCurrentResultDivs: function () { // 清除面积测量时的临时结果
            var that = this;
            dojo.query('.result-div').forEach(function (node) {
                if (dojo.query(node).attr('data-randomid')[0] == that._currentRandomId) {
                    domConstruct.destroy(node);
                }
            });
        },
        _createProcessResultDiv: function (result, mapPoint) { // 创建结果div
            var that=this;
            var screen = this._mapView.toScreen(mapPoint);
            var unit="";
            if(that.toolname=='area'){
                unit="平方米";
                if(result>100000){
                    result=result/1000000;
                    unit="平方公里"
                }
            }else  if(that.toolname=="length"){
                unit="米";
                if(result>1000){
                    result=result/1000;
                    unit="公里";
                }
            }
            result=parseFloat(result);
            var html = that._tpl(that.processTemplate, {
                result: result.toFixed(2),
                unit: unit,
                screenx: screen.x - 5,
                screeny: screen.y + 10,
                mapx: mapPoint.x,
                mapy: mapPoint.y,
                randomId: this._currentRandomId
            });
            dojo.query(this._mapView.container).query('.esri-view-root').addContent(html);
        },
        /**
         * 显示结果
         * @param result
         * @param mapPoint
         * @private
         */
        _createResultDiv: function (result, mapPoint) { // 创建结果div
            var that=this;
            var screen = this._mapView.toScreen(mapPoint);
            var unit="";
            var resultType="";
            if(that.toolname=='area'){
                unit="平方米";
                if(result>100000){
                    result=result/1000000;
                    unit="平方公里"
                }
            }else  if(that.toolname=="length"){
                unit="米";
                resultType="总长：";
                if(result>1000){
                    result=result/1000;
                    unit="公里";
                }
            }
            result=parseFloat(result);
            var html = that._tpl(that.resultTemplate, {
                result: result.toFixed(2),
                resultType:resultType,
                unit: unit,
                screenx: screen.x - 5,
                screeny: screen.y + 10,
                mapx: mapPoint.x,
                mapy: mapPoint.y,
                randomId: this._currentRandomId
            });
            dojo.query(this._mapView.container).query('.esri-view-root').addContent(html);
        },
        _calResultDiv: function () { // 计算结果div对应到mapPoint时的位置
            try{
                var me = this;
                var nodes = dojo.query('.result-div').forEach(function (node) {
                    var mapx = dojo.query(node).attr('data-mapx')[0];
                    var mapy = dojo.query(node).attr('data-mapy')[0];
                    var x=parseFloat(mapx);
                    var y= parseFloat(mapy);
                    var point=new Point(x,y,me._mapView.spatialReference);
                    var screen = me._mapView.toScreen(point);
                    node.style.left = (screen.x - 5) + 'px';
                    node.style.top = (screen.y + 10) + 'px';
                });
                dojo.query('.clear-div').forEach(function (node) {
                    var dnode = dojo.query(node);
                    var mapx = dnode.attr('data-mapx')[0];
                    var mapy = dnode.attr('data-mapy')[0];
                    var leftOffset = dnode.attr('data-left-offset');
                    var x=parseFloat(mapx);
                    var y= parseFloat(mapy);
                    var point=new Point(x,y,me._mapView.spatialReference);
                    var screen = me._mapView.toScreen(point);
                    node.style.left = (screen.x + parseFloat(leftOffset)) + 'px';
                    node.style.top = (screen.y - 7) + 'px';
                });
            }catch (e) {
                console.log(e);
            }
            
        },
        _getUnitCh: function (flag) {
            var that=this;
            var unit="";
            if(that.toolname=='area'){
                unit="平方米";
                if(flag==1){
                    unit="平方公里"
                }
            }else  if(that.toolname=="length"){
                unit="米";
                if(flag==1){
                    unit="公里";
                }
            }
            return unit;
        },
        /**
         * 计算面积
         */
        clacArea:function (geo){
            try {
                return Math.abs(geometryEngine.planarArea(geo, "square-meters").toFixed(1));
            }catch (e) {
                return "0";
            }
        },

        /**
         * 通过编辑的节点构建面
         * @param vertices
         * @returns {*}
         */
        createPolygon: function(vertices) {
            var that=this;
            return new Polygon({
                rings: vertices,
                spatialReference: that._mapView.spatialReference
            });
        },
        /**
         * 生成Graphic
         * @param polygon
         * @returns {*}
         */
        createGraphic:function(polygon) {
            graphic = new Graphic({
                geometry: polygon,
                symbol: {
                    type: "simple-fill", // autocasts as SimpleFillSymbol
                    color: [178, 102, 234, 0.8],
                    style: "solid",
                    outline: { // autocasts as SimpleLineSymbol
                        color: "#FD8045",
                        width: 1
                    }
                }
            });
            return graphic;
        },

        // 通过编辑的节点构建线
        createPolyline:function (vertices) {
            var that=this;
            return new Polyline({
                paths: vertices,
                spatialReference: that._mapView.spatialReference
            });
        },

    createPolylineGraphic:function (polyline) {
        var polylineGraphic = new Graphic({
            geometry: polyline,
            symbol: {
                type: "simple-line",
                color: "#FD8045",
                width: 1
        }
        });
        return polylineGraphic;
    },
        /**
         * 计算面积
         * @param geometry
         * @returns {*}
         * @private
         */
        _measure: function (geometry) {
            var that=this;
            var result;
            if (!geometry) {
                return;
            }
            switch (this.toolname) {
                case that.tools.AREA:
                    if (geometry.type === 'polygon') {
                        this._unit || (this._unit = 'square-meters');
                        if (this._options.coordinates === 'projected') {
                            result = geometryEngine.planarArea(geometry, this._unit);
                        } else {
                            result = geometryEngine.geodesicArea(geometry, this._unit);
                        }
                        result = Math.abs(result);
                        break;
                    }
                case that.tools.LENGTH:
                    if (geometry.type === 'polyline') {
                        this._unit || (this._unit = 'meters');
                        if (this._options.coordinates === 'projected') {
                            result = geometryEngine.planarLength(geometry, this._unit);
                        } else {
                            result = geometryEngine.geodesicLength(geometry, this._unit);
                        }
                        result = Math.abs(result);
                        break;
                    }
            };

            if (this._parseResult) {
                result = this._parseResult(result);
            }
            if (this._decimal) { // 测量结果的小数保留
                var decimal=parseInt(this._decimal);
                result=result.toFixed(decimal);
            }else{
                result=result.toFixed(2);
            }

            return result;
        },

        clearAllResult:function () {
            var that=this;
            if(that._tempGraphicLayer!=null){
                that._tempGraphicLayer.removeAll();
                that._tempGraphicLayer=null;
            }
            if(that._drawNodeGraphicLayer!=null){
                that._drawNodeGraphicLayer.removeAll();
                that._drawNodeGraphicLayer=null;
            }



            dojo.query('.result-div').forEach(function (node) {
                domConstruct.destroy(node);
            });

            dojo.query('.clear-div').forEach(function (node) {
                domConstruct.destroy(node);
            });

        }

});
});
